﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace IGGCore
{
    public class ThreeStarsCalculator
    {
        private static CultureInfo enca = new CultureInfo("en-ca");

        private static void SetPitchingGamescore(Player player)
        {
            int score = 1000;
            player.GameLines = new string[2];

            float ip = (float.Parse(player.IP, enca));
            string line = player.EarnedRuns + " er in " + ip.ToString("#.#") + " innings" ;

            if (int.Parse(player.Outs) == 0)
            {
                score -= 100000;
                line = "---";
            }
            
            // OUTS
            score += int.Parse(player.Outs) * 80;

            // STRIKEOUTS
            score += player.StrikeOuts * 40;
            if (player.StrikeOuts > 2)
            {
                line += ". " + player.StrikeOuts + " K";
            }
            if (player.StrikeOuts > 7)
            {
                score += player.StrikeOuts * 10;
            }

            // RUNS
            score -= player.EarnedRuns * 100;

            // BB
            score -= int.Parse(player.BB) * 40;
            if (ip > 4 && int.Parse(player.BB) == 0)
            {
                score += 75;
                line += ". 0 walks";
            }

            // NO HITTER
            if (ip > 8.8 && player.Hits == 0)
            {
                 if (player.BB == "0")
                 {
                    player.GameScore += 15000000;
                    line = "A MOTHER-FREAKING PERFECT GAME!";
                }
                else
                {
                    player.GameScore += 5000000;
                    line = "A FREAKING NO-HITTER!";
                }
            }
            else if (ip > 8.8 && player.Hits == 1)
            {
                // one-hitter
                player.GameScore += 2000;
                line += ". A one-hitter!";
            }
            else if (ip > 8.8 && player.Hits == 1)
            {
                // one-hitter
                player.GameScore += 2000;
                line += ". Only two hits allowed!";
            }

            player.GameScore = score;
            player.GameLines[0] = line;
        }

        /// <summary>
        /// Calculate the star power for a pitcher
        /// </summary>
        private static void SetPitchingStarPlayer(Player player)
        {
            player.GameLines = new string[2];
            
            float ip = (float.Parse(player.IP, enca));
            player.GameLines[0] = player.EarnedRuns + " er in " + ip.ToString("#.#") + " innings";
            if (ip > 8.8 && player.Hits == 0)
            {
                // no-hitter
                player.GameScore = 1000;
                if (player.BB == "0")
                {
                    player.GameLines[0] = "A MOTHER-FREAKING PERFECT GAME!";
                }
                else
                {
                    player.GameLines[0] = "A FREAKING NO-HITTER!";
                }
            }
            else if (ip > 8.8 && player.Hits == 1)
            {
                // one-hitter
                player.GameScore = 100;
                if (player.BB == "0")
                {
                    player.GameLines[0] = "A one-hitter!";
                }
            }
            else if (ip > 3)
            {
                float ratio = (player.EarnedRuns + 1) / ((ip + 1) * 2F);
                // 9 ip and no er = 0.050
                // 9 ip and 1 er =  0.100
                // 8 ip and no er = 0.055
                // 8 ip and 1 er =  0.111
                // 8 ip and 2 er =  0.160
                // 8 ip and 3 er =  0.222
                // 7 ip and no er = 0.062
                // 7 ip and 1 er =  0.125
                // 7 ip and 2 er =  0.187
                // 7 ip and 3 er =  0.250
                // 6 ip and no er = 0.714
                // 6 ip and 1 er =  
                // 6 ip and 2 er =  
                // 5 ip and no er = 
                // 5 ip and 1 er = 
                // 4 ip and no er = 
                // 4 ip and 1 er = 

                if (ratio < 0.05F)
                {
                    player.GameScore += 30;
                }
                else if (ratio < 0.07F)
                {
                    player.GameScore += 25;
                }
                else if (ratio < 0.08F)
                {
                    player.GameScore += 20;
                }
                else if (ratio < 0.1F)
                {
                    player.GameScore += 15;
                }
                else if (ratio < 0.15)
                {
                    player.GameScore += 10;
                }
                else if (ratio < 0.18)
                {
                    player.GameScore += 8;
                }
                else if (ratio < 0.2)
                {
                    player.GameScore += 5;
                }

                //if (ip > 4)
                //{
                //    if (player.EarnedRuns == 3)
                //    {
                //        player.GameScore += 6;
                //    }
                //    else if (player.EarnedRuns == 2)
                //    {
                //        player.GameScore += 10;
                //    }
                //    else if (player.EarnedRuns == 1)
                //    {
                //        player.GameScore += 20;
                //    }
                //    if (player.EarnedRuns == 0)
                //    {
                //        player.GameScore += 50;
                //    }
                //}

                // COMPLETED GAME
                if (float.Parse(player.IP, enca) > 8.8)
                {
                    player.GameScore += 30;
                    // SHOUTOUT
                    if (player.R == "0")
                    {
                        player.GameScore += 30;
                        player.GameLines[0] = "A shutout!";
                    }
                }

                if (player.StrikeOuts > 5)
                {
                    player.GameScore += (player.StrikeOuts - 5) * 3;
                    player.GameLines[0] += ", " + player.StrikeOuts + " K";
                }
            }
            else
            {
                if (player.BB == "0")
                {
                    player.GameScore += 10;
                }
                else if (player.BB == "1")
                {
                    player.GameScore += 5;
                }
                if (ip < 4)
                {
                    player.GameScore += 1;
                }
            }

            
        }

        /// <summary>
        /// Calculate the star power for an offensive player
        /// </summary>
        private static void SetOffenseStarPlayer(Player player)
        {
            player.GameLines = new string[2];
            player.GameLines[0] = player.Hits + "/" + player.Ab;
            int runs = int.Parse(player.R);
            int bb = int.Parse(player.BB);

            if (player.Homeruns > 0)
            {
                player.GameLines[0] += ", " + player.Homeruns + " hr";
            }
            if (runs > 0)
            {
                if (runs == 1 && player.Homeruns == 1)
                {
                    // nothing to mention
                }
                else
                {
                    player.GameLines[0] += ", " + runs + " run";
                    if (runs > 1)
                    {
                        player.GameLines[0] += "s";
                    }
                }

            }
            if (player.RBI > 0)
            {
                player.GameLines[0] += ", " + player.RBI + " rbi";
            }
            if (player.Homeruns == 1 && player.RBI == 1 && runs == 1)
            {
                player.GameLines[0] = player.Hits + "/" + player.Ab + ", 1 hr";
            }
            if (player.StolenBases > 0)
            {
                player.GameLines[0] += ", " + player.StolenBases + " sb";
            }
            if (bb > 0)
            {
                player.GameLines[0] += ", " + bb + " bb";
            }

            player.GameScore += (player.Hits * 5) + (player.RBI * 4) + (player.Homeruns * 3) + (runs * 2) + (bb * 1) + (player.StolenBases * 2);
            if (player.Hits == 0 && player.RBI > 0)
            {
                player.GameScore += (player.RBI * 5) + (player.Homeruns * 3) + (runs * 2) + (bb * 1) + (player.StolenBases * 2);
            }
            if (player.Ab > 3 && (player.Hits == player.Ab))
            {
                player.GameScore += (((player.Ab + bb) - 1) * 4);
            }
            else if (player.Ab == 2 && (player.Hits == player.Ab) && bb > 0)
            {
                player.GameScore += (((player.Ab + bb) - 1) * 3);
            }
            if (player.Homeruns == 2)
            {
                player.GameScore += 10;
            }
            else if (player.Homeruns > 2)
            {
                player.GameScore += 25;
            }
        }

        public static Player[] GetThreeStarPlayers(List<Game> games)
        {
            Player[] stars = new Player[4];
            List<Player> starList = new List<Player>();
            foreach (Game game in games)
            {
                Boxscore boxscore = game.Boxscore;
                if (boxscore == null)
                {
                    continue;
                }
                foreach (Player player in boxscore.AwayBatting)
                {
                    SetOffenseStarPlayer(player);
                    player.TeamAbbr = game.AwayTeam.Abbrv;
                    starList.Add(player);
                }
                foreach (Player player in boxscore.HomeBatting)
                {
                    SetOffenseStarPlayer(player);
                    player.TeamAbbr = game.HomeTeam.Abbrv;
                    starList.Add(player);
                }
                foreach (Player player in boxscore.AwayPitching)
                {
                    SetPitchingStarPlayer(player);
                    player.TeamAbbr = game.AwayTeam.Abbrv;
                    starList.Add(player);
                }
                foreach (Player player in boxscore.HomePitching)
                {
                    SetPitchingStarPlayer(player);
                    player.TeamAbbr = game.HomeTeam.Abbrv;
                    starList.Add(player);
                }
            }

            if (starList.Count > 3)
            {
                starList.Sort();

                stars[0] = starList[0];
                stars[1] = starList[1];
                stars[2] = starList[2];
                stars[3] = starList[3];
            }
            return stars;
        }

        public static Player[] GetOffensiveThreeStarPlayers(List<Game> games)
        {
            Player[] stars = new Player[4];
            List<Player> starList = new List<Player>();
            foreach (Game game in games)
            {
                Boxscore boxscore = game.Boxscore;
                if (boxscore == null)
                {
                    continue;
                }
                foreach (Player player in boxscore.AwayBatting)
                {
                    SetOffenseStarPlayer(player);
                    player.TeamAbbr = game.AwayTeam.Abbrv;
                    starList.Add(player);
                }
                foreach (Player player in boxscore.HomeBatting)
                {
                    SetOffenseStarPlayer(player);
                    player.TeamAbbr = game.HomeTeam.Abbrv;
                    starList.Add(player);
                }
            }

            if (starList.Count > 3)
            {
                starList.Sort();

                stars[0] = starList[0];
                stars[1] = starList[1];
                stars[2] = starList[2];
                stars[3] = starList[3];
            }
            return stars;
        }

        public static List<Player> GetOffensiveThreeStarPlayers(Game game)
        {
            List<Player> starList = new List<Player>();
            Boxscore boxscore = game.Boxscore;
            if (boxscore == null)
            {
                return starList;
            }
            foreach (Player player in boxscore.AwayBatting)
            {
                SetOffenseStarPlayer(player);
                player.TeamAbbr = game.AwayTeam.Abbrv;
                starList.Add(player);
            }
            foreach (Player player in boxscore.HomeBatting)
            {
                SetOffenseStarPlayer(player);
                player.TeamAbbr = game.HomeTeam.Abbrv;
                starList.Add(player);
            }

            starList.Sort();
            return starList;
        }

        public static List<Player> GetPitchingThreeStarPlayers(List<Game> games)
        {
            List<Player> starList = new List<Player>();
            foreach (Game game in games)
            {
                Boxscore boxscore = game.Boxscore;
                if (boxscore == null)
                {
                    continue;
                }
                foreach (Player player in boxscore.AwayPitching)
                {
                    SetPitchingGamescore(player);
                    player.TeamAbbr = game.AwayTeam.Abbrv;
                    starList.Add(player);
                }
                foreach (Player player in boxscore.HomePitching)
                {
                    SetPitchingGamescore(player);
                    player.TeamAbbr = game.HomeTeam.Abbrv;
                    starList.Add(player);
                }
            }

            starList.Sort();
            return starList;
        }

        /// <summary>
        /// Get the 3 best players for a particular game
        /// </summary>
        public static Player[] GetThreeStarPlayers(Game game, bool byTeam)
        {
            Boxscore boxscore = game.Boxscore;
            Player[] stars = new Player[4];
            List<Player> starList = new List<Player>();

            foreach (Player player in boxscore.AwayBatting)
            {
                SetOffenseStarPlayer(player);
                player.TeamAbbr = game.AwayTeam.Abbrv;
                starList.Add(player);
            }
            foreach (Player player in boxscore.HomeBatting)
            {
                SetOffenseStarPlayer(player);
                player.TeamAbbr = game.HomeTeam.Abbrv;
                starList.Add(player);
            }
            //foreach (Player player in boxscore.AwayPitching)
            //{
            //    SetPitchingStarPlayer(player);
            //    player.TeamAbbr = game.AwayTeam.Abbrv;
            //    starList.Add(player);
            //}
            //foreach (Player player in boxscore.HomePitching)
            //{
            //    SetPitchingStarPlayer(player);
            //    player.TeamAbbr = game.HomeTeam.Abbrv;
            //    starList.Add(player);
            //}

            if (starList.Count > 3)
            {
                starList.Sort();

                stars[0] = starList[0];
                stars[1] = starList[1];
                stars[2] = starList[2];
                stars[3] = starList[3];

                if (byTeam)
                {
                    stars[0] = starList[0];
                    int indx = 1;
                    while (starList[indx].TeamAbbr == stars[0].TeamAbbr)
                    {
                        indx++;
                    }
                    stars[1] = starList[indx];
                }
            }
            
            return stars;
        }
    }
}
